package api

import (
	"SamWaf/global"
	"SamWaf/model/common/response"
	"SamWaf/model/request"
	response2 "SamWaf/model/response"
	"SamWaf/utils"
	"SamWaf/wafconfig"
	"crypto/tls"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"os"
	"path/filepath"
	"time"

	"github.com/gin-gonic/gin"
)

type WafVpConfigApi struct {
}

// UpdateIpWhitelistApi 更新IP白名单配置
func (w *WafVpConfigApi) UpdateIpWhitelistApi(c *gin.Context) {
	var req request.WafVpConfigIpWhitelistUpdateReq
	err := c.ShouldBindJSON(&req)
	if err == nil {

		// 调用配置文件更新函数
		err = wafconfig.UpdateIpWhitelist(req.IpWhitelist)
		if err != nil {
			response.FailWithMessage("更新IP白名单失败: "+err.Error(), c)
		} else {
			response.OkWithMessage("更新IP白名单成功", c)
		}
	} else {
		response.FailWithMessage("解析请求失败", c)
	}
}

// GetIpWhitelistApi 获取IP白名单配置
func (w *WafVpConfigApi) GetIpWhitelistApi(c *gin.Context) {
	// 直接从全局变量获取IP白名单
	ipWhitelist := global.GWAF_IP_WHITELIST

	// 构造响应数据
	resp := response2.WafVpConfigIpWhitelistGetResp{
		IpWhitelist: ipWhitelist,
	}

	response.OkWithDetailed(resp, "获取IP白名单成功", c)
}

// UpdateSslEnableApi 更新SSL启用状态
func (w *WafVpConfigApi) UpdateSslEnableApi(c *gin.Context) {
	var req request.WafVpConfigSslEnableUpdateReq
	err := c.ShouldBindJSON(&req)
	if err == nil {
		// 调用配置文件更新函数
		err = wafconfig.UpdateSslEnable(req.SslEnable)
		if err != nil {
			response.FailWithMessage("更新SSL启用状态失败: "+err.Error(), c)
		} else {
			response.OkWithMessage("更新SSL启用状态成功，需要重启管理端生效", c)
		}
	} else {
		response.FailWithMessage("解析请求失败", c)
	}
}

// GetSslStatusApi 获取SSL状态
func (w *WafVpConfigApi) GetSslStatusApi(c *gin.Context) {
	// 获取SSL启用状态
	sslEnable := global.GWAF_SSL_ENABLE

	// 检查证书文件是否存在
	certPath := filepath.Join(utils.GetCurrentDir(), "data", "ssl", "manager", "domain.crt")
	keyPath := filepath.Join(utils.GetCurrentDir(), "data", "ssl", "manager", "domain.key")

	hasCert := false
	certExpireAt := ""
	certDomain := ""
	certContent := ""
	keyContent := ""

	// 检查证书文件是否存在
	if _, err := os.Stat(certPath); err == nil {
		if _, err := os.Stat(keyPath); err == nil {
			hasCert = true
			// 读取证书文件获取证书信息
			certInfo := getCertInfo(certPath)
			certExpireAt = certInfo.ExpireAt
			certDomain = certInfo.Domain

			// 读取证书内容
			if certData, err := os.ReadFile(certPath); err == nil {
				certContent = string(certData)
			}

			// 读取私钥内容
			if keyData, err := os.ReadFile(keyPath); err == nil {
				keyContent = string(keyData)
			}
		}
	}

	// 构造响应数据
	resp := response2.WafVpConfigSslStatusGetResp{
		SslEnable:    sslEnable,
		HasCert:      hasCert,
		CertExpireAt: certExpireAt,
		CertDomain:   certDomain,
		CertContent:  certContent,
		KeyContent:   keyContent,
	}

	response.OkWithDetailed(resp, "获取SSL状态成功", c)
}

// UploadSslCertApi 上传SSL证书
func (w *WafVpConfigApi) UploadSslCertApi(c *gin.Context) {
	var req request.WafVpConfigSslUploadReq
	err := c.ShouldBindJSON(&req)
	if err != nil {
		response.FailWithMessage("解析请求失败", c)
		return
	}

	// 验证证书内容不为空
	if req.CertContent == "" || req.KeyContent == "" {
		response.FailWithMessage("证书内容和私钥内容不能为空", c)
		return
	}

	// 校验证书可用性
	if err := validateCertificate(req.CertContent, req.KeyContent); err != nil {
		response.FailWithMessage("证书校验失败: "+err.Error(), c)
		return
	}

	// 创建目录
	sslDir := filepath.Join(utils.GetCurrentDir(), "data", "ssl", "manager")
	if err := os.MkdirAll(sslDir, 0755); err != nil {
		response.FailWithMessage("创建证书目录失败: "+err.Error(), c)
		return
	}

	// 保存证书文件
	certPath := filepath.Join(sslDir, "domain.crt")
	keyPath := filepath.Join(sslDir, "domain.key")

	// 写入证书文件
	if err := os.WriteFile(certPath, []byte(req.CertContent), 0644); err != nil {
		response.FailWithMessage("保存证书文件失败: "+err.Error(), c)
		return
	}

	// 写入私钥文件
	if err := os.WriteFile(keyPath, []byte(req.KeyContent), 0600); err != nil {
		// 如果私钥保存失败，删除证书文件
		os.Remove(certPath)
		response.FailWithMessage("保存私钥文件失败: "+err.Error(), c)
		return
	}

	response.OkWithMessage("上传SSL证书成功，需要重启管理端生效", c)
}

// validateCertificate 校验证书可用性
func validateCertificate(certContent, keyContent string) error {
	// 解析证书
	certBlock, _ := pem.Decode([]byte(certContent))
	if certBlock == nil {
		return fmt.Errorf("无效的证书格式")
	}

	cert, err := x509.ParseCertificate(certBlock.Bytes)
	if err != nil {
		return fmt.Errorf("解析证书失败: %v", err)
	}

	// 检查证书是否过期
	now := time.Now()
	if now.Before(cert.NotBefore) {
		return fmt.Errorf("证书尚未生效")
	}
	if now.After(cert.NotAfter) {
		return fmt.Errorf("证书已过期")
	}

	// 解析私钥
	keyBlock, _ := pem.Decode([]byte(keyContent))
	if keyBlock == nil {
		return fmt.Errorf("无效的私钥格式")
	}

	// 尝试加载证书和私钥配对
	_, err = tls.X509KeyPair([]byte(certContent), []byte(keyContent))
	if err != nil {
		return fmt.Errorf("证书和私钥不匹配: %v", err)
	}

	return nil
}

// CertInfo 证书信息
type CertInfo struct {
	ExpireAt string // 过期时间
	Domain   string // 域名
}

// getCertInfo 获取证书信息
func getCertInfo(certPath string) CertInfo {
	info := CertInfo{
		ExpireAt: "",
		Domain:   "",
	}

	certData, err := os.ReadFile(certPath)
	if err != nil {
		return info
	}

	certBlock, _ := pem.Decode(certData)
	if certBlock == nil {
		return info
	}

	cert, err := x509.ParseCertificate(certBlock.Bytes)
	if err != nil {
		return info
	}

	// 获取过期时间
	info.ExpireAt = cert.NotAfter.Format("2006-01-02 15:04:05")

	// 获取域名信息
	if cert.Subject.CommonName != "" {
		info.Domain = cert.Subject.CommonName
	}

	// 如果有SAN（Subject Alternative Name），优先使用
	if len(cert.DNSNames) > 0 {
		// 将所有域名用逗号连接
		info.Domain = ""
		for i, dns := range cert.DNSNames {
			if i > 0 {
				info.Domain += ", "
			}
			info.Domain += dns
		}
	}

	return info
}

// RestartManagerApi 重启管理端
func (w *WafVpConfigApi) RestartManagerApi(c *gin.Context) {
	response.OkWithMessage("管理端将在1秒后重启，请稍候5-10秒后重新访问", c)

	// 延迟后重启，给时间返回响应
	go func() {
		time.Sleep(1 * time.Second)

		// 触发重启通道
		if global.GWAF_CHAN_MANAGER_RESTART != nil {
			select {
			case global.GWAF_CHAN_MANAGER_RESTART <- 1:
				// 发送成功
			default:
				// 通道已满，说明已经有重启请求在处理中
			}
		}
	}()
}
